package xj.graph2d.template.uml;

import static javax.swing.SwingConstants.HORIZONTAL;
import static javax.swing.SwingConstants.VERTICAL;
import xj.graph2d.DrawShape;
import xj.graph2d.DrawShapeConstants;
import xj.graph2d.GraphEdgeBase;
import xj.graph2d.Label;
import xj.graph2d.TextShape;
import xj.graph2d.shapes.BoxLabel;
import xj.graph2d.template.UMLStateDiagramTemplate;
import xj.graph2d.template.UMLTemplate;
import xj.model.uml.Action;
import xj.model.uml.Event;
import xj.model.uml.Transition;

public class UMLTransitionModelListener extends UMLAbstractModelListener {

  public UMLTransitionModelListener() {
  }

  public UMLTransitionModelListener(UMLTemplate template) {
    this(null, null, template);
  }

  public UMLTransitionModelListener(Object model, DrawShape shape,
      UMLTemplate template) {
    super(model, shape, template);
  }

  @Override
  public void updateModel() {
    if (shape instanceof GraphEdgeBase && model instanceof Transition) {
      GraphEdgeBase edge = (GraphEdgeBase) shape;
      Transition tmodel = (Transition) model;
      Label lshape = edge.getLabelShape(DrawShapeConstants.ROLE_EDGE_LABEL);

      // String label = edge.getLabel(DrawShape.ROLE_EDGE_LABEL);
      String event = null;
      String guard = null;
      String action = null;

      if (lshape instanceof TextShape) {
	String label = lshape.getText();
	if (label != null) {
	  int i, j;
	  i = label.indexOf('[');
	  if (i >= 0) {
	    event = label.substring(0, i).trim();
	    j = label.indexOf(']', i);
	    if (j > i) {
	      guard = label.substring(i + 1, j).trim();
	      int k = label.indexOf('/', j);
	      if (k > j) {
		action = label.substring(k + 1).trim();
	      } else {
		action = label.substring(j + 1).trim();
	      }
	    } else {
	      guard = label.substring(i + 1).trim();
	    }
	  } else {
	    j = label.indexOf('/', i);
	    if (j >= 0) {
	      event = label.substring(0, j).trim();
	      action = label.substring(j + 1).trim();
	    } else {
	      event = label.trim();
	    }
	  }
	}
	tmodel.setEventName(event);
	tmodel.setGuardText(guard);
	tmodel.setActionBody(action);
      } else if (lshape instanceof BoxLabel) {
	BoxLabel box = (BoxLabel) lshape;
	int n = box.getShapeCount();
	for (int i = 0; i < n; i++) {
	  DrawShape s = box.getShape(i);
	  if (s instanceof TextShape) {
	    TextShape t = (TextShape) s;
	    String prompt = t.getPrompt();
	    if ("event".equals(prompt)) {
	      event = t.getText();
	      tmodel.setEventName(event);
	    } else if ("guard".equals(prompt)) {
	      guard = t.getText();
	      tmodel.setGuardText(guard);
	    } else if ("action".equals(prompt)) {
	      action = t.getText();
	      tmodel.setActionBody(action);
	    }
	  }
	}
      }
    }
  }

  @Override
  public void updateShape() {
    if (shape instanceof GraphEdgeBase && model instanceof Transition) {
      GraphEdgeBase edge = (GraphEdgeBase) shape;
      Transition tmodel = (Transition) model;
      String event = tmodel.getEventName();
      String guard = tmodel.getGuardText();
      String action = tmodel.getActionBody();

      Label lshape = edge.getLabelShape(DrawShapeConstants.ROLE_EDGE_LABEL);
      if (lshape == null || lshape instanceof TextShape) {
	String label = makeLabel(event, guard, action);
	lshape = setLabel(edge, DrawShapeConstants.ROLE_EDGE_LABEL, label,
			  "event", false, UMLStateDiagramTemplate.TRANSITION_FONT,
			  UMLStateDiagramTemplate.TRANSITION_TEXT_COLOR);
	if (lshape != null) {
	  lshape.setDisplayName("Trigger");
	}
      } else if (lshape instanceof BoxLabel) {
	BoxLabel box = (BoxLabel) lshape;
	int n = box.getShapeCount();
	for (int i = 0; i < n; i++) {
	  DrawShape s = box.getShape(i);
	  if (s instanceof TextShape) {
	    TextShape t = (TextShape) s;
	    String prompt = t.getPrompt();
	    if ("event".equals(prompt)) {
	      t.setText(event);
	    } else if ("guard".equals(prompt)) {
	      t.setText(guard);
	    } else if ("action".equals(prompt)) {
	      t.setText(action);
	    }
	  }
	}
      } else {

      }
    }
  }

  static String makeLabel(String event, String guard, String action) {
    String label = event;
    if (event == null) {
      label = "";
    }
    if (guard != null && guard.length() > 0) {
      label += ("[" + guard + "]");
    }
    if (action != null && action.length() > 0) {
      label += ("/" + action);
    }
    return label;
  }

  public void splitLabel(boolean vertical) {
    if (shape instanceof GraphEdgeBase && model instanceof Transition) {
      GraphEdgeBase edge = (GraphEdgeBase) shape;
      Transition tmodel = (Transition) model;
      String[] labels = new String[3];
      String event = null; 
      Event e = tmodel.getEvent();
      if (e != null) { 
	event = e.getName();
      }
      labels[0] = event; 
      String guard = tmodel.getGuardText();
      if (guard != null && guard.length() > 0) {
	labels[1] = guard;
      } else {
	labels[1] = null;
      }
      String action = null;
      Action a = tmodel.getAction();
      if (a != null) { 
	action = a.getBody();
      }
      if (action != null && action.length() > 0) {
	labels[2] = action;
      } else {
	labels[2] = null;
      }
      Label lshape = setLabel(edge, DrawShapeConstants.ROLE_EDGE_LABEL,
			      vertical ? VERTICAL : HORIZONTAL, labels, prompt, prefix, suffix,
			      UMLStateDiagramTemplate.TRANSITION_FONT,
			      UMLStateDiagramTemplate.TRANSITION_TEXT_COLOR);
      if (lshape != null) {
	lshape.setDisplayName("Trigger");
      }
    }
  }

  static String[] prompt = { "event", "guard", "action" };

  static String[] prefix = { null, "[", "/" };

  static String[] suffix = { null, "]", null };

  public void mergeLabel() {
    if (shape instanceof GraphEdgeBase && model instanceof Transition) {
      GraphEdgeBase edge = (GraphEdgeBase) shape;
      Transition tmodel = (Transition) model;
      String event = tmodel.getEventName();
      String guard = tmodel.getGuardText();
      String action = tmodel.getActionBody();

      String label = makeLabel(event, guard, action);
      Label lshape = setLabel(edge, DrawShapeConstants.ROLE_EDGE_LABEL, label,
	  "event", false, UMLStateDiagramTemplate.TRANSITION_FONT,
	  UMLStateDiagramTemplate.TRANSITION_TEXT_COLOR);
      if (lshape != null) {
	lshape.setDisplayName("Trigger");
      }
    }
  }

  public static final int EVENT_MENU = 0x1;

  public static final int GUARD_MENU = 0x2;

  public static final int ACTION_MENU = 0x4;

  public void hide(int hidemenu) {
    if (shape instanceof GraphEdgeBase && model instanceof Transition) {
      GraphEdgeBase edge = (GraphEdgeBase) shape;
      Transition tmodel = (Transition) model;
      String event = tmodel.getEventName();
      String guard = tmodel.getGuardText();
      String action = tmodel.getActionBody();

      Label lshape = edge.getLabelShape(DrawShapeConstants.ROLE_EDGE_LABEL);
      if (lshape instanceof BoxLabel) {
	BoxLabel box = (BoxLabel) lshape;
	int n = box.getShapeCount();
	int menu = 0;
	int count = 0;
	for (int i = 0; i < n; i++) {
	  DrawShape s = box.getShape(i);
	  if (s instanceof TextShape) {
	    TextShape t = (TextShape) s;
	    String prompt = t.getPrompt();
	    if ("event".equals(prompt)) {
	      if (hidemenu != EVENT_MENU) {
		menu += EVENT_MENU;
		count++;
	      }
	    } else if ("guard".equals(prompt)) {
	      if (hidemenu != GUARD_MENU) {
		menu += GUARD_MENU;
		count++;
	      }
	    } else if ("action".equals(prompt)) {
	      if (hidemenu != ACTION_MENU) {
		menu += ACTION_MENU;
		count++;
	      }
	    }
	  }
	}
	showLabel(menu, count, edge, event, guard, action);
      }
    }
  }

  public void show(int showmenu) {
    if (shape instanceof GraphEdgeBase && model instanceof Transition) {
      GraphEdgeBase edge = (GraphEdgeBase) shape;
      Transition tmodel = (Transition) model;
      String event = tmodel.getEventName();
      String guard = tmodel.getGuardText();
      String action = tmodel.getActionBody();

      Label lshape = edge.getLabelShape(DrawShapeConstants.ROLE_EDGE_LABEL);
      if (lshape instanceof BoxLabel) {
	BoxLabel box = (BoxLabel) lshape;
	int n = box.getShapeCount();
	int menu = 0;
	int count = 0;
	for (int i = 0; i < n; i++) {
	  DrawShape s = box.getShape(i);
	  if (s instanceof TextShape) {
	    TextShape t = (TextShape) s;
	    String prompt = t.getPrompt();
	    if ("event".equals(prompt)) {
	      menu += EVENT_MENU;
	      count++;
	    } else if ("guard".equals(prompt)) {
	      menu += GUARD_MENU;
	      count++;
	    } else if ("action".equals(prompt)) {
	      menu += ACTION_MENU;
	      count++;
	    }
	  }
	}
	if ((menu & showmenu) == 0) {
	  menu += showmenu;
	  count++;
	}
	showLabel(menu, count, edge, event, guard, action);
      }
    }
  }

  protected void showLabel(int menu, int count, GraphEdgeBase edge,
      String event, String guard, String action) {
    String[] labels0 = new String[count];
    String[] prompt0 = new String[count];
    String[] prefix0 = new String[count];
    String[] suffix0 = new String[count];

    int i = 0;
    if ((menu & EVENT_MENU) != 0) {
      labels0[i] = event;
      prompt0[i] = prompt[0];
      prefix0[i] = prefix[0];
      suffix0[i] = suffix[0];
      i++;
    }
    if ((menu & GUARD_MENU) != 0) {
      labels0[i] = guard;
      prompt0[i] = prompt[1];
      prefix0[i] = prefix[1];
      suffix0[i] = suffix[1];
      i++;
    }
    if ((menu & ACTION_MENU) != 0) {
      labels0[i] = action;
      prompt0[i] = prompt[2];
      prefix0[i] = prefix[2];
      suffix0[i] = suffix[2];
      i++;
    }

    Label lshape = setLabel(edge, DrawShapeConstants.ROLE_EDGE_LABEL, VERTICAL,
			    labels0, prompt0, prefix0, suffix0,
			    UMLStateDiagramTemplate.TRANSITION_FONT,
			    UMLStateDiagramTemplate.TRANSITION_TEXT_COLOR);
    if (lshape != null) {
      lshape.setDisplayName("Trigger");
    }

  }

}
